/**
 * Copyright (C) 2010 Cloudfarming <info@cloudfarming.nl>
 *
 * Licensed under the Eclipse Public License - v 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.eclipse.org/legal/epl-v10.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package nl.cloudfarming.client.db.local;

import java.io.PrintWriter;
import nl.cloudfarming.client.db.EntityManagerProviderSupport;
import nl.cloudfarming.client.db.PersistingModule;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.EntityManager;
import nl.cloudfarming.client.db.local.jpa.JPASessionLocator;
import nl.cloudfarming.client.lib.hsqldb.JavaAssistHelper;
import nl.cloudfarming.client.logging.AppLogFactory;
import nl.cloudfarming.client.logging.AppLogger;
import org.hsqldb.Server;
import org.openide.util.Lookup;
import org.openide.util.Lookup.Result;
import org.openide.util.LookupEvent;
import org.openide.util.LookupListener;
import org.openide.util.lookup.ServiceProvider;

/**
 *
 * @author Timon Veenstra
 */
@ServiceProvider(service = EntityManagerProviderSupport.class)
public class LocalEntityManagerProvider implements EntityManagerProviderSupport {

    private final Result<PersistingModule> persistingModuleResult = Lookup.getDefault().lookupResult(PersistingModule.class);
    private final Map<String, JPASessionLocator> moduleLocators = new HashMap<String, JPASessionLocator>();

    public LocalEntityManagerProvider() {

        AppLogger logger = AppLogFactory.getLogger(LocalEntityManagerProvider.class); 
        //
        // initialize the out of process hsql db server
        // must be done before hibernate gets initialized in the JPASessionLocator per module
        //
        Server server = new Server();
        server.setDaemon(false);
        server.setDatabaseName(0, "cloudfarming");
        server.setDatabasePath(0, "file:data/cfdb");
        server.setSilent(true);
        server.setLogWriter(new PrintWriter(System.out));
        server.setErrWriter(new PrintWriter(System.err));
        server.start();
        //
        // resets javassist classloader to the contextclassloader so hibernate proxy can be found.
        //
        JavaAssistHelper.createJavaAssistClassLoader();
        //
        // retrieve the initial know persiting modules and create entity manager factories for them
        // add listener for runtime enabled persiting modules
        //
        updateProviders(persistingModuleResult);
        persistingModuleResult.addLookupListener(new LookupListener() {

            @Override
            public void resultChanged(LookupEvent ev) {
                updateProviders((Result<PersistingModule>) ev.getSource());
            }
        });


    }

    //
    // update the map of entity manager providers
    //
    private void updateProviders(Result<PersistingModule> result) {
        for (PersistingModule module : result.allInstances()) {
            if (!moduleLocators.containsKey(module.getModuleName())) {
                moduleLocators.put(module.getModuleName(), new JPASessionLocator(module));
            }
        }

    }

    //
    // retrieve an entityManager, call is proxied to the provider for the given module
    //
    @Override
    public EntityManager getEntityManager(String moduleName) {
        if (moduleLocators.containsKey(moduleName)) {
            return this.moduleLocators.get(moduleName).getEntityManager();
        }
        throw new IllegalArgumentException("No persistence information know about module " + moduleName + ", no PersistingModule service provided?");
    }
}
